package simulation;

import java.util.Hashtable;

public class Cache {
	int cacheSize;
	int lineSize;
	int associativity;
	int cacheAccessTime;
	int writePolicy;
	Hashtable<Integer, Integer[]> data = new Hashtable<Integer, Integer[]>();
	int[] usage;
	int[] dirtyBits;
	int accesses;
	int misses;

	public Cache() {

	}

	public Cache(int cacheSize, int lineSize, int associativity,
			int cacheAccessTime, int writePolicy) {
		this.cacheSize = cacheSize;
		this.lineSize = lineSize;
		this.associativity = associativity;
		this.cacheAccessTime = cacheAccessTime;
		this.writePolicy = writePolicy;
		usage = new int[cacheSize / lineSize];
		dirtyBits = new int[cacheSize / lineSize];
	}

	public int getLeastUsed(int start, int end) {
		int min = usage[start];
		for (int i = start + 1; i <= end; i++) {
			if (usage[i] < min)
				min = usage[i];
		}
		return min;
	}

	public double getHitRatio(){
		double acc = accesses;
		double mis = misses;
		if(acc>0)
			return (acc-mis)/acc;
		else
			return -1;
	}
	
	public int getCacheLine(int memoryAddress) {
		int cacheLine = 0;
		if (associativity == cacheSize / lineSize) {
			if (data.size() < (cacheSize / lineSize)) {
				cacheLine = data.size();
			} else {
				cacheLine = this.getLeastUsed(0, (cacheSize / lineSize) - 1);
			}
		} else {
			if (associativity == 1) {
				cacheLine = (memoryAddress/(lineSize/2)) % (cacheSize / lineSize);
			} else {
				int x = (memoryAddress/(lineSize/2))
						% ((cacheSize / lineSize) / associativity);
				boolean flag = false;
				for (int i = 0; i < associativity; i++) {
					if (!data.containsKey(associativity * x + i)) {
						cacheLine = associativity * x + i;
						flag = true;
						break;
					}
				}
				if (!flag) {
					cacheLine = this.getLeastUsed(associativity * x,
							(associativity * x + associativity) - 1);
				}
			}
		}
		return cacheLine;
	}
}